//
//  NetworkHelper.m
//  Kugou-OC
//
//  Created by BH on 16/5/30.
//  Copyright © 2016年 Sunny. All rights reserved.
//

#import "NetworkHelper.h"
#import "GlobalDefine.h"
#import "CLGifLoadView.h"
#import <AFNetworking/AFNetworking.h>
#import <AFHTTPRequestOperationManager+Synchronous.h>

// 项目打包上线都不会打印日志，因此可放心。
#ifdef DEBUG
#define AppLog(s, ... ) NSLog( @"[%@：in line: %d]-->[message: %@]", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define AppLog(s, ... )
#endif

static NSString *kg_privateNetworkBaseUrl = nil;
static BOOL kg_isEnableInterfaceDebug = YES;
static BOOL kg_AutoEncode = NO;
static NSDictionary *kg_httpHeader = nil;
static ResponseType kg_responseType = kResponseTypeJSON;
static RequestType  kg_requestType  = kRequestTypeJSON;

@interface NetworkHelper ()

@property(nonatomic,strong)CLGifLoadView *loadview;

@end

@implementation NetworkHelper

+(instancetype)shareNetwork{
    static NetworkHelper *net = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        net = [[self alloc] init];
    });
    
    return net;
}

-(NSString*)baseUrl{
    return kg_privateNetworkBaseUrl;
}

-(void)updateBaseUrl:(NSString *)baseUrl{
    kg_privateNetworkBaseUrl = baseUrl;
}

-(BOOL)isDebug{
    return kg_isEnableInterfaceDebug;
}

-(void)enableInterfaceDebug:(BOOL)isDebug{
    kg_isEnableInterfaceDebug = isDebug;
}

-(BOOL)shouldAutoEncodeUrl{
    return kg_AutoEncode;
}

-(void)shouldAutoEncodeUrl:(BOOL)autoEncode{
    kg_AutoEncode = autoEncode;
}

-(void)configResponseType:(ResponseType)responsetype{
    kg_responseType = responsetype;
}

-(void)configRequestType:(RequestType)requesttype{
    kg_requestType = requesttype;
}

-(void)configCommonHttpHeaders:(NSDictionary *)httpHeader{
    kg_httpHeader = httpHeader;
}

/*-----------------------------------------------------------------------------------------------------------------------------*/
-(void)getDataWithUrl:(NSString *)url view:(UIView *)view success:(SuccessBlock)success failure:(FailureBlock)failure{
    [self getDataWithUrl:url params:nil view:view success:success failure:failure];
}

-(void)getDataWithUrl:(NSString *)url params:(NSDictionary *)params view:(UIView *)view success:(SuccessBlock)success failure:(FailureBlock)failure{
    
    if ([self shouldAutoEncodeUrl]) {
        url = [self encodeUrl:url];
    }
    
    if ([self checkNetworkStatus:view]) {
        
        AFHTTPRequestOperationManager *manager = [self manager];
        [manager GET:url parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
            if (success) {
                [_loadview setState:CLLoadStateFinish];
                success(responseObject);
            }
            
            if ([self isDebug]) {
                [self logWithSuccessResponse:responseObject url:operation.response.URL.absoluteString params:params];
            }
            
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            if (failure) {
                
                [_loadview setState:CLLoadStateFailed];
                failure(error);
            }
            
            if ([self isDebug]) {
                [self logWithSuccessResponse:error url:operation.response.URL.absoluteString params:params];
            }
        }];
    }else{
        [_loadview setState:CLLoadStateFailed];
    }
}

-(void)syncGetDataWithUrl:(NSString *)url params:(NSDictionary *)params view:(UIView *)view success:(SuccessBlock)success failure:(FailureBlock)failure{
    if ([self shouldAutoEncodeUrl]) {
        url = [self encodeUrl:url];
    }
    
    if ([self checkNetworkStatus:view]) {
        
        AFHTTPRequestOperationManager *manager = [self manager];
        NSError *error = nil;
        id result = [manager syncGET:url parameters:params operation:NULL error:&error];
        
//        id json = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingMutableContainers error:&error];
        
        if (result) {
            [_loadview setState:CLLoadStateFinish];
            success(result);
        }
        
        if ([self isDebug]) {
            [self logWithSuccessResponse:result url:url params:params];
        }
        
        if (error) {
            [_loadview setState:CLLoadStateFailed];
            failure(error);
        }
        
    }else{
        [_loadview setState:CLLoadStateFailed];
    }
}

-(void)postDataWithUrl:(NSString *)url params:(NSDictionary *)params view:(UIView *)view success:(SuccessBlock)success failure:(FailureBlock)failure{
    if ([self checkNetworkStatus:view]) {
        
        AFHTTPRequestOperationManager *manager = [self manager];
        [manager POST:url parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
            if (success) {
                [_loadview setState:CLLoadStateFinish];
                success(responseObject);
            }
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            if (failure) {
                [_loadview setState:CLLoadStateFailed];
                failure(error);
            }
        }];
    }else{
        [_loadview setState:CLLoadStateFailed];
    }
}

-(void)syncPostDataWithUrl:(NSString *)url params:(NSDictionary *)params view:(UIView *)view success:(SuccessBlock)success failure:(FailureBlock)failure{
    
    if ([self shouldAutoEncodeUrl]) {
        url = [self encodeUrl:url];
    }
    
    if ([self checkNetworkStatus:view]) {
        
        AFHTTPRequestOperationManager *manager = [self manager];
        NSError *error = nil;
        NSData *result = [manager syncPOST:url parameters:params operation:NULL error:&error];
        id json = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingMutableContainers error:&error];
        
        if (json) {
            [_loadview setState:CLLoadStateFinish];
            success(json);
        }
        
        if ([self isDebug]) {
            [self logWithSuccessResponse:json url:url params:params];
        }
        
        if (error) {
            [_loadview setState:CLLoadStateFailed];
            failure(error);
        }
        
    }else{
        [_loadview setState:CLLoadStateFailed];
    }
}

#pragma mark - Private
-(AFHTTPRequestOperationManager *)manager{
    AFHTTPRequestOperationManager *manager = nil;
    //设置baseurl
    if ([self baseUrl] != nil) {
        manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:[self baseUrl]]];
    }else{
        manager = [AFHTTPRequestOperationManager manager];
    }
    
    //设置请求数据类型
    switch (kg_requestType) {
        case kRequestTypeJSON:
            manager.requestSerializer = [AFJSONRequestSerializer serializer];
            break;
        case kRequestTypePlainText:
            manager.requestSerializer = [AFHTTPRequestSerializer serializer];
            break;
        default:
            break;
    }
    
    //设置响应数据类型
    switch (kg_responseType) {
        case kResponseTypeJSON:
            manager.responseSerializer = [AFJSONResponseSerializer serializer];
            break;
        case kResponseTypeXML:
            manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
            break;
        case kResponseTypeData:
            manager.responseSerializer = [AFHTTPResponseSerializer serializer];
            break;
        default:
            break;
    }
    
    manager.requestSerializer.stringEncoding = NSUTF8StringEncoding;
    
    //设置请求头
    [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    for (NSString *key in kg_httpHeader.allKeys) {
        if (kg_httpHeader[key] != nil) {
            [manager.requestSerializer setValue:kg_httpHeader[key] forHTTPHeaderField:key];
        }
    }
    
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"application/json",@"text/html",@"text/json",@"text/javascript",@"text/xml",@"image/*"]];
    
    // 设置允许同时最大并发数量，过大容易出问题
    manager.operationQueue.maxConcurrentOperationCount = 3;
    
    return manager;
}

- (void)downloadWithUrl:(NSString *)url
             saveToPath:(NSString *)saveToPath
               progress:(DownloadProgress)progressBlock
                success:(SuccessBlock)success
                failure:(FailureBlock)failure{
    
    NSURLRequest *downloadRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:downloadRequest];
    
    op.outputStream = [NSOutputStream outputStreamToFileAtPath:saveToPath append:NO];
    [op setDownloadProgressBlock:progressBlock];
    
    [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        if (success) {
            // 将下载后的文件路径返回
            success(saveToPath);
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        if (failure) {
            failure(error);
        }
    }];
    
    [op start];
}

#pragma mark - private
//检查网络
-(BOOL)checkNetworkStatus:(UIView *)view{
    
    NSInteger flag = [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus;
    
    if (_loadview) {
        [_loadview removeFromSuperview];
    }
    
    _loadview = [[CLGifLoadView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT-64-90)];
    [view addSubview:_loadview];
    __weak CLGifLoadView *load = _loadview;
    [_loadview setRetryBlcok:^{
        [load setState:CLLoadStateLoading];
    }];
    
    if (flag > 0) {
        [_loadview setState:CLLoadStateLoading];
        return YES;
    }else{
        [_loadview setState:CLLoadStateFailed];
        return NO;
    }
}

- (NSString *)encodeUrl:(NSString *)url {
    return [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"`#%^{}\"[]|\\<> "].invertedSet];
}

- (void)logWithSuccessResponse:(id)response url:(NSString *)url params:(NSDictionary *)params {
    AppLog(@"\nabsoluteUrl: %@\n params:%@\n response:%@\n\n",
              url,
              params,
              [self tryToParseData:response]);
}

- (id)tryToParseData:(id)responseData {
    if ([responseData isKindOfClass:[NSData class]]) {
        // 尝试解析成JSON
        if (responseData == nil) {
            return responseData;
        } else {
            NSError *error = nil;
            NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseData
                                                                     options:NSJSONReadingMutableContainers
                                                                       error:&error];
            
            if (error != nil) {
                return responseData;
            } else {
                return response;
            }
        }
    } else {
        return responseData;
    }
}

@end
